home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / sml_nj / 93src.lha / src / runtime / export-rs6000-aix < prev    next >
Encoding:
Text File  |  1993-02-09  |  17.3 KB  |  758 lines

  1. /* Modified by Lal.George@att.com for use in the SML/NJ compiler */
  2.  
  3. /* Modified by Andrew.Vignaux@comp.vuw.ac.nz to get it to work :-) */
  4.  
  5. /* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 1, or (at your option)
  10.     any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. In other words, you are welcome to use, share and improve this program.
  22. You are forbidden to forbid anyone else to use, share and improve
  23. what you give them.   Help stamp out software-hoarding!  */
  24.  
  25. /*
  26.  * unexec.c - Convert a running program into an a.out file.
  27.  *
  28.  * Author:    Spencer W. Thomas
  29.  *         Computer Science Dept.
  30.  *         University of Utah
  31.  * Date:    Tue Mar  2 1982
  32.  * Modified heavily since then.
  33.  *
  34.  * Synopsis:
  35.  *    unexec (new_name, a_name, data_start, bss_start, entry_address)
  36.  *    char *new_name, *a_name;
  37.  *    unsigned data_start, bss_start, entry_address;
  38.  *
  39.  * Takes a snapshot of the program and makes an a.out format file in the
  40.  * file named by the string argument new_name.
  41.  * If a_name is non-NULL, the symbol table will be taken from the given file.
  42.  * On some machines, an existing a_name file is required.
  43.  *
  44.  * The boundaries within the a.out file may be adjusted with the data_start
  45.  * and bss_start arguments.  Either or both may be given as 0 for defaults.
  46.  *
  47.  * Data_start gives the boundary between the text segment and the data
  48.  * segment of the program.  The text segment can contain shared, read-only
  49.  * program code and literal data, while the data segment is always unshared
  50.  * and unprotected.  Data_start gives the lowest unprotected address.
  51.  * The value you specify may be rounded down to a suitable boundary
  52.  * as required by the machine you are using.
  53.  *
  54.  * Specifying zero for data_start means the boundary between text and data
  55.  * should not be the same as when the program was loaded.
  56.  * If NO_REMAP is defined, the argument data_start is ignored and the
  57.  * segment boundaries are never changed.
  58.  *
  59.  * Bss_start indicates how much of the data segment is to be saved in the
  60.  * a.out file and restored when the program is executed.  It gives the lowest
  61.  * unsaved address, and is rounded up to a page boundary.  The default when 0
  62.  * is given assumes that the entire data segment is to be stored, including
  63.  * the previous data and bss as well as any additional storage allocated with
  64.  * break (2).
  65.  *
  66.  * The new file is set up to start at entry_address.
  67.  */
  68.  
  69. #include <a.out.h>
  70. #include <errno.h>
  71. #include <stdio.h>
  72. #include <sys/stat.h>
  73.  
  74. #define PERROR(arg) {perror(arg); return -1;}
  75.  
  76. extern int     _data;
  77. extern int     _edata;
  78. extern int     _text;
  79. extern int     _etext;
  80. extern int     _end;
  81.  
  82.  
  83. static long         block_copy_start;
  84. static struct filehdr    f_hdr;
  85. static struct aouthdr     f_ohdr;         
  86. long             bias;            /* bias to add for growth */
  87. long             lnnoptr;        /* pointer to line no. info */
  88. #define SYMS_START     block_copy_start
  89.  
  90. static long     text_scnptr;
  91. static long     data_scnptr;
  92.  
  93. static long     load_scnptr;
  94. static long     orig_load_scnptr;
  95. static long     orig_data_scnptr;
  96.  
  97. #define ADDR_CORRECT(x) ((int)(x))
  98. #define MAX_SECTIONS 16
  99. static int pagemask;
  100.  
  101.  
  102. extern char     ** global_argv;
  103. extern int     old_high;
  104.  
  105.  
  106. static char * start_of_text()
  107.     {
  108.     return ((char *) 0x10000000);
  109.     }
  110.  
  111.  
  112. static char * start_of_data ()
  113.     {
  114.     return ((char *) 0x20000000);
  115.     }
  116.  
  117.  
  118. static report_error (file, fd)
  119. char *file;
  120. int fd;
  121.     {
  122.     if (fd) close (fd);
  123.     chatting ("Failure operating on %s", file);
  124.     }
  125.  
  126.  
  127.  
  128. static report_error_1 (fd, msg, a1, a2)
  129. int     fd;
  130. char     *msg;
  131. int     a1, a2;
  132.     {
  133.       close (fd);
  134.       chatting (msg, a1, a2);
  135.     }
  136.  
  137.  
  138.  
  139. int sys_write (fildes, buf, nbyte)
  140. int      fildes;
  141. char      *buf;
  142. unsigned int nbyte;
  143.     {
  144.       register int rtnval;
  145.  
  146.       while ((rtnval = write (fildes, buf, nbyte)) == -1
  147.          && (errno == 4));
  148.     return (rtnval);
  149.     }
  150.  
  151.  
  152. unexec (new, a_name, data_start, bss_start, entry_address)
  153. int        new;
  154. char         *a_name;
  155. unsigned    data_start, bss_start, entry_address;
  156.     {
  157.     int a_out = -1;
  158.  
  159.     if (a_name && (a_out = open (a_name, 0)) < 0){ PERROR (a_name); }
  160.  
  161.       if (make_hdr (new,a_out,data_start,bss_start,entry_address,a_name)<0 ||
  162.               copy_text_and_data (new) < 0 ||
  163.               copy_sym (new, a_out, a_name) < 0 ||
  164.         adjust_lnnoptrs (new, a_out) < 0  ||
  165.             unrelocate_symbols (new, a_out, a_name) < 0)
  166.         {
  167.         return -1;    
  168.             }
  169.  
  170.       if (a_out >= 0)  close (a_out);
  171.     fchmod(new,0755);
  172.       return 0;
  173.     }
  174.  
  175.  
  176.  
  177. #define CHECK_SCNHDR(ptr, name, flags)                     \
  178.   if (strcmp(s->s_name, name) == 0) {                     \
  179.     if (s->s_flags != flags) {                         \
  180.       chatting("unexec: %x flags where %x expected in %s section.\n", \
  181.           s->s_flags, flags, name);                 \
  182.     }                                     \
  183.     if (ptr) {                                 \
  184.       chatting("unexec: duplicate section header for section %s.\n", \
  185.           name);                             \
  186.     }                                     \
  187.     ptr = s;                                 \
  188.   }
  189.  
  190. static int make_hdr (new, a_out, data_start, bss_start, 
  191.              entry_address, a_name)
  192. int         new, a_out;
  193. unsigned     data_start, bss_start, entry_address;
  194. char         *a_name;
  195. #define ERROR0(msg)     report_error_1 (new, msg, 0, 0); return -1
  196. #define ERROR1(msg,x)     report_error_1 (new, msg, x, 0); return -1
  197. #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
  198.     {
  199.       register int scns;
  200.       unsigned int bss_end;
  201.  
  202.       struct scnhdr section[MAX_SECTIONS];
  203.       struct scnhdr * f_thdr;        /* Text section header */
  204.       struct scnhdr * f_dhdr;        /* Data section header */
  205.       struct scnhdr * f_bhdr;        /* Bss section header */
  206.       struct scnhdr * f_lhdr;        /* Loader section header */
  207.       struct scnhdr * f_tchdr;    /* Typechk section header */
  208.       struct scnhdr * f_dbhdr;    /* Debug section header */
  209.       struct scnhdr * f_xhdr;        /* Except section header */
  210.  
  211.       load_scnptr = orig_load_scnptr = lnnoptr = 0;
  212.       
  213.     pagemask = getpagesize () - 1;
  214.  
  215.       /* Adjust text/data boundary. */
  216.       data_start = (long) start_of_data ();
  217.     data_start = ADDR_CORRECT (data_start);
  218.  
  219.       data_start = data_start & ~pagemask; 
  220.  
  221. /*      
  222. **    bss_end = ADDR_CORRECT (sbrk (0)) + pagemask;
  223. */
  224.     bss_end    = ADDR_CORRECT (old_high) + pagemask;
  225.       bss_end &= ~ pagemask;
  226.  
  227.     /* Adjust data/bss boundary. */
  228.       if (bss_start != 0)
  229.             {
  230.               bss_start = (ADDR_CORRECT (bss_start) + pagemask);
  231.               /* (Up) to page bdry. */
  232.               bss_start &= ~ pagemask;
  233.               if (bss_start > bss_end)
  234.             {
  235.               ERROR1("unexec: bss_start (%u) is past end of program",
  236.               bss_start);
  237.             }
  238.             }
  239.       else
  240.             bss_start = bss_end;
  241.  
  242.       if (data_start > bss_start)    /* Can't have negative data size. */
  243.             {
  244.               ERROR2 ("unexec: data_start (%u) > bss_start (%u)",
  245.                   data_start, bss_start);
  246.            }
  247.  
  248.       /* Salvage as much info from the existing file as possible */
  249.       block_copy_start = 0;
  250.       f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
  251.       f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
  252.       
  253.     if (a_out >= 0)
  254.             {
  255.               if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
  256.             {
  257.               PERROR (a_name);
  258.             }
  259.               block_copy_start += sizeof (f_hdr);
  260.               
  261.         if (f_hdr.f_opthdr > 0)
  262.             {
  263.               if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != 
  264.                 sizeof (f_ohdr))
  265.                     {
  266.                       PERROR (a_name);
  267.                     }
  268.               block_copy_start += sizeof (f_ohdr);
  269.             }
  270.               if (f_hdr.f_nscns > MAX_SECTIONS)
  271.             {
  272.               ERROR0 ("unexec: too many section headers");
  273.             }
  274.               /* Loop through section headers */
  275.               for (scns = 0; scns < f_hdr.f_nscns; scns++) 
  276.             {
  277.             struct scnhdr *s = §ion[scns];
  278.             if (read (a_out, s, sizeof (*s)) != sizeof (*s))
  279.                   {
  280.                     PERROR (a_name);
  281.                   }
  282.             if (s->s_scnptr > 0L)
  283.                   {
  284.                         if (block_copy_start < s->s_scnptr + s->s_size)
  285.                           block_copy_start = s->s_scnptr + s->s_size;
  286.                   }
  287.  
  288.             CHECK_SCNHDR(f_thdr, _TEXT, STYP_TEXT);
  289.             CHECK_SCNHDR(f_dhdr, _DATA, STYP_DATA);
  290.             CHECK_SCNHDR(f_bhdr, _BSS, STYP_BSS);
  291.             CHECK_SCNHDR(f_lhdr, _LOADER, STYP_LOADER);
  292.             CHECK_SCNHDR(f_dbhdr, _DEBUG,  STYP_DEBUG);
  293.             CHECK_SCNHDR(f_tchdr, _TYPCHK,  STYP_TYPCHK);
  294.             CHECK_SCNHDR(f_xhdr, _EXCEPT,  STYP_EXCEPT);
  295.                   }
  296.  
  297.         if (f_thdr == 0)
  298.             {
  299.               ERROR1 ("unexec: couldn't find \"%s\" section", _TEXT);
  300.             }
  301.         if (f_dhdr == 0)
  302.             {
  303.               ERROR1 ("unexec: couldn't find \"%s\" section", _DATA);
  304.             }
  305.               if (f_bhdr == 0)
  306.             {
  307.               ERROR1 ("unexec: couldn't find \"%s\" section", _BSS);
  308.             }
  309.             }
  310.           else
  311.                 {
  312.                   ERROR0 ("can't build a COFF file from scratch yet");
  313.                 }
  314.  
  315.           orig_data_scnptr = f_dhdr->s_scnptr;
  316.         orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
  317.  
  318.         /* Now we alter the contents of all the f_*hdr variables
  319.              ** to correspond to what we want to dump. 
  320.         */
  321.           f_hdr.f_flags |= (F_RELFLG | F_EXEC);        /* Why? */
  322.  
  323.         f_ohdr.dsize = bss_start - ((unsigned) &_data);
  324.         f_ohdr.bsize = bss_end - bss_start;
  325.  
  326.         f_dhdr->s_size = f_ohdr.dsize;
  327.         f_bhdr->s_size = f_ohdr.bsize;
  328.         f_bhdr->s_paddr = f_ohdr.dsize;
  329.         f_bhdr->s_vaddr = f_ohdr.dsize;
  330.  
  331.         /* fix scnptr's */
  332.         {
  333.         long ptr;
  334.  
  335.             for (scns = 0; scns < f_hdr.f_nscns; scns++) 
  336.             {
  337.                   struct scnhdr *s = §ion[scns];
  338.             if (scns == 0)
  339.             ptr = s->s_scnptr;
  340.  
  341.             if (s->s_scnptr != 0)
  342.                 {
  343.                 s->s_scnptr = ptr;
  344.                 }
  345.  
  346.             if ((s->s_flags & 0xffff) == STYP_PAD)
  347.                 {
  348.                 /*
  349.                 ** the text_start should probably be o_algntext 
  350.                 ** but that doesn't seem to change
  351.                 */
  352.                 if (f_ohdr.text_start != 0) /* && scns != 0 */
  353.                     {
  354.                     s->s_size = 512 - (s->s_scnptr % 512);
  355.                     if (s->s_size == 512)
  356.                     s->s_size = 0;
  357.                     }
  358.                 }
  359.  
  360.             ptr = ptr + s->s_size;
  361.             }
  362.  
  363.         bias = ptr - block_copy_start;
  364.         }
  365.  
  366.         /* fix other pointers */
  367.       for (scns = 0; scns < f_hdr.f_nscns; scns++) 
  368.         {
  369.             struct scnhdr *s = §ion[scns];
  370.  
  371.             if (s->s_relptr != 0)
  372.                   {
  373.             s->s_relptr += bias;
  374.                   }
  375.             if (s->s_lnnoptr != 0)
  376.                   {
  377.             if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
  378.             s->s_lnnoptr += bias;
  379.                   }
  380.           }
  381.  
  382.     if (f_hdr.f_symptr > 0L)
  383.             {
  384.               f_hdr.f_symptr += bias;
  385.             }
  386.  
  387.       text_scnptr = f_thdr->s_scnptr;
  388.       data_scnptr = f_dhdr->s_scnptr;
  389.       load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
  390.       block_copy_start = orig_load_scnptr;
  391.  
  392.       if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
  393.             {
  394.               
  395.             }
  396.  
  397.       if (f_hdr.f_opthdr > 0)
  398.             {
  399.               if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
  400.             {
  401.             report_error("reading filehdr", new);
  402.             return -1;
  403.             }
  404.             }
  405.  
  406.       for (scns = 0; scns < f_hdr.f_nscns; scns++) 
  407.         {
  408.             struct scnhdr *s = §ion[scns];
  409.             if (write (new, s, sizeof (*s)) != sizeof (*s))
  410.                   {
  411.             report_error("reading section header",new);
  412.             return -1;
  413.                   }
  414.           }
  415.  
  416.       return (0);
  417.     }
  418.  
  419.  
  420. #define write_segment(fd,start,end) bulletproofWrite0(fd,start,end-start)
  421.  
  422. static int copy_text_and_data (new)
  423. int new;
  424.     {
  425.       register char *end;
  426.       register char *ptr;
  427.  
  428.       lseek (new, (long) text_scnptr, 0);
  429.       ptr = start_of_text () + text_scnptr;
  430.       end = ptr + f_ohdr.tsize;
  431.       write_segment (new, ptr, end);
  432.  
  433.       lseek (new, (long) data_scnptr, 0);
  434.       ptr = (char *) &_data;
  435.       end = ptr + f_ohdr.dsize;
  436.       write_segment (new, ptr, end);
  437.  
  438.     return 0;
  439.     }
  440.  
  441.  
  442.  
  443. static int copy_sym (new, a_out, a_name)
  444. int new, a_out;
  445. char *a_name;
  446.     {
  447.       char page[1024];
  448.       int n;
  449.  
  450.       if (a_out < 0) return 0;
  451.  
  452.       if (SYMS_START == 0L) return 0;
  453.  
  454.       if (lnnoptr && lnnoptr < SYMS_START)
  455.             lseek (a_out, lnnoptr, 0);    /* start copying from there */
  456.       else
  457.             lseek (a_out, SYMS_START, 0);    /* Position a.out to symtab. */
  458.  
  459.       while ((n = read (a_out, page, sizeof page)) > 0)
  460.             {
  461.               if (write (new, page, n) != n) 
  462.             { 
  463.             chatting("copy_sym: Error in reading a.out\n");
  464.             return -1;
  465.             }
  466.           if (n < 0) 
  467.             { 
  468.             chatting("copy_sym: cannot write -ve number of bytes\n");
  469.             return -1;
  470.             }
  471.         }
  472.       return 0;
  473.     }
  474.  
  475.  
  476. adjust_lnnoptrs (writedesc, readdesc)
  477. int     writedesc;
  478. int     readdesc;
  479.     {
  480.       register int     nsyms;
  481.       register int    new = writedesc;
  482.     struct syment     symentry;
  483.       union auxent     auxentry;
  484.  
  485.       if (!lnnoptr || !f_hdr.f_symptr)  return 0;
  486.  
  487.     lseek (new, f_hdr.f_symptr, 0);
  488.     for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
  489.         {
  490.         read (new, &symentry, SYMESZ);
  491.         if (symentry.n_numaux)
  492.             {
  493.             read (new, &auxentry, AUXESZ);
  494.               nsyms++;
  495.               if (ISFCN (symentry.n_type)) 
  496.                 {
  497.                     auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
  498.                     lseek (new, -AUXESZ, 1);
  499.                     write (new, &auxentry, AUXESZ);
  500.                   }
  501.             }
  502.             }
  503.     }
  504.  
  505. unrelocate_symbols (new, a_out, a_name)
  506. int new, a_out;
  507. char *a_name;
  508.     {
  509.       register int i;
  510.       register int l;
  511.       register LDREL *ldrel;
  512.       LDHDR ldhdr;
  513.       LDREL ldrel_buf [20];
  514.       ulong t_start = &_text;
  515.       ulong d_start = &_data;
  516.       int * p;
  517.       int dirty;
  518.  
  519.       if (load_scnptr == 0) return 0;
  520.  
  521.       lseek (a_out, orig_load_scnptr, 0);
  522.       if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
  523.             {
  524.         chatting("Could not read loader section header\n");
  525.         return -1;
  526.             }
  527.  
  528. #define SYMNDX_TEXT    0
  529. #define SYMNDX_DATA    1
  530. #define SYMNDX_BSS    2
  531.       l = 0;
  532.       for (i = 0; i < ldhdr.l_nreloc; i++, l--, ldrel++)
  533.             {
  534.               if (l == 0) 
  535.             {
  536.             lseek (a_out,
  537.                           orig_load_scnptr+LDHDRSZ+LDSYMSZ*ldhdr.l_nsyms 
  538.                 + LDRELSZ*i,
  539.                    0);
  540.  
  541.             l = ldhdr.l_nreloc - i;
  542.             if (l > sizeof (ldrel_buf) / LDRELSZ)
  543.                   l = sizeof (ldrel_buf) / LDRELSZ;
  544.  
  545.             if (read (a_out, ldrel_buf, l * LDRELSZ) != l * LDRELSZ)
  546.                   {
  547.                     PERROR (a_name);
  548.                   }
  549.             ldrel = ldrel_buf;
  550.               }
  551.               dirty = 0;
  552.  
  553.               /* this code may not be necessary */
  554.               /* I originally had == in the "assignment" and it     
  555.           still unrelocated */
  556.  
  557.               /* move the BSS loader symbols to the DATA segment */
  558.               if (ldrel->l_rsecnm == f_ohdr.o_snbss)
  559.         ldrel->l_rsecnm = f_ohdr.o_sndata, dirty++;
  560.  
  561.               if (ldrel->l_symndx == SYMNDX_BSS)
  562.         ldrel->l_symndx = SYMNDX_DATA, dirty++;
  563.  
  564.               if (dirty)
  565.             {
  566.               lseek (new,
  567.                  load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
  568.                  0);
  569.  
  570.               if (write (new, ldrel, LDRELSZ) != LDRELSZ)
  571.                     {
  572.                 chatting("could not write to output file\n");
  573.                 return -1;
  574.                     }
  575.             }
  576.  
  577.               if (ldrel->l_rsecnm == f_ohdr.o_sndata)
  578.             {
  579.               int orig_int;
  580.  
  581.               lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0);
  582.  
  583.               if (read (a_out, (void *) &orig_int, sizeof (orig_int))
  584.                 != sizeof (orig_int))
  585.                     {
  586.                       PERROR (a_name);
  587.                    }
  588.  
  589.               switch (ldrel->l_symndx) 
  590.                     {
  591.                   case SYMNDX_TEXT:
  592.                         p = (int *) (d_start + ldrel->l_vaddr);
  593.                         orig_int = * p - (t_start - f_ohdr.text_start);
  594.                         break;
  595.  
  596.                   case SYMNDX_DATA:
  597.                   case SYMNDX_BSS:
  598.                     p = (int *) (d_start + ldrel->l_vaddr);
  599.                     orig_int = * p - (d_start - f_ohdr.data_start);
  600.                    break;
  601.                   }
  602.  
  603.               lseek (new, data_scnptr + ldrel->l_vaddr, 0);
  604.               if (write (new, (void *) &orig_int, sizeof (orig_int)) !=
  605.                       sizeof (orig_int))
  606.                     {
  607.                       chatting("could not write to output file\n");
  608.                 return -1;
  609.                     }
  610.             }
  611.             }
  612.     }
  613.  
  614.  
  615.  
  616. #define MAXPATHLEN     512
  617. #define isabsolutePath(name) (name[0] == '/')
  618.  
  619.  
  620. hasSlash (name) char * name;
  621. {
  622.     int n = strlen(name);
  623.     int i;
  624.  
  625.     for (i = 0; i<n; i++) 
  626.     if (name[i] == '/') return 1;
  627.  
  628.     return 0;
  629. }
  630.  
  631.  
  632. /*
  633. ** searchPath (name) -- search PATH environment variable
  634. **    - modifies name 
  635. *    - returns 1 on success and 0 on failure.
  636. */
  637. searchPath(name) char * name;
  638. {
  639.     char * path;
  640.     int  n;
  641.     char fileName[256];
  642.  
  643.     int i,j;
  644.  
  645.     path = getenv("PATH");
  646.     n = strlen (path);
  647.  
  648.     j = 0;
  649.     for (i=0; i < n; i++) 
  650.     {
  651.         if (path[i] != ':') fileName[j++] = path[i];
  652.         else 
  653.         {
  654.             struct stat statBuff;
  655.  
  656.             fileName[j] = '/';
  657.             fileName[j+1] = '\0';
  658.             strcat(fileName,name);
  659.             if (stat(fileName, & statBuff) == 0)
  660.             {
  661.                 strcpy(name,fileName);
  662.                 return 1;
  663.             }
  664.             else j = 0;
  665.         }
  666.     }
  667.     return 0;
  668. }
  669.  
  670.  
  671. baseName (name) char * name;
  672.     {
  673.     int i, n = strlen(name);
  674.  
  675.     for (i=n; i>=0 && name[i] != '/'; i--) 
  676.         name[i] = '\0';
  677.     }
  678.  
  679. /*
  680. ** chaseLinks (buff) -- chases links until the executable is found.
  681. **    - modifies buff
  682. **    - returns 1 on success and 0 on failure.
  683. **    ToDo: - Should probably check that the file returned is executable
  684. */
  685. char * chaseLinks(buff) char buff[];
  686. {
  687.     int     n;
  688.     char    ans[MAXPATHLEN];
  689.  
  690.     while (1) 
  691.     {
  692.         if ((n=readlink(buff,ans,MAXPATHLEN-1)) == -1) 
  693.         {
  694.             switch (errno) 
  695.             {
  696.             case EINVAL:    return 1;
  697.             case ENOENT:    chatting("chaseLinks: invalid file\n");
  698.                     return 0;
  699.             default:    chatting("chaseLinks: impossible\n");
  700.                     return 0;
  701.             }
  702.         }
  703.         else
  704.         ans[n] = '\0';
  705.         if (isabsolutePath(ans)) 
  706.             {
  707.             strncpy(buff,ans,n+1);
  708.             }
  709.         else
  710.             {
  711.             baseName(buff);
  712.             if (strlen(buff) + strlen(ans) >= MAXPATHLEN)
  713.                 {
  714.                 chatting("chaseLinks: path name too long\n");
  715.                 return 0;
  716.                 }
  717.             strncat(buff,ans,n);
  718.             }
  719.     }
  720. }
  721.  
  722.  
  723. getaoutname(name) char *name;
  724. {
  725.     if (!(isabsolutePath(name) || hasSlash(name)))
  726.     if (searchPath(name) == 0) 
  727.         {
  728.         chatting("chaseLinks: Could not find executable in path!\n");
  729.         return 0;
  730.         }
  731.     return(chaseLinks(name));
  732. }
  733.  
  734.  
  735.     
  736.  
  737. export(filid)
  738. int filid;
  739. {
  740.     char     buff[MAXPATHLEN];
  741.     
  742.     strcpy(buff,global_argv[0]);
  743.  
  744.     if (getaoutname(buff) == 0) 
  745.     {
  746.         chatting("export: getaoutname failed\n");
  747.         return 1;
  748.     }
  749.     
  750.     if (unexec(filid,buff,0,0,0) == 0) return 0;
  751.     else 
  752.     {
  753.         chatting ("export: Unexec failed\n");
  754.         return 1;
  755.     }
  756. }
  757.  
  758.